package test;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;

/**
 * 摩天大楼建筑群，5*5格子里
 * 
 * @author Administrator
 * 
 */
@SuppressWarnings("serial")
public class Skyscrapers extends JFrame {

	Skyscraper[][] skyscrapers;

	private int length, width;

	private JTextArea sumText;

	boolean bPrint = false;

	private Random random;

	Skyscrapers(int length, int width) {
		this.length = length;
		this.width = width;
		random = new Random();
	}

	public void init() {
		this.setTitle("Skyscrapers");
		this.setBounds(250, 200, 400, 300);
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		BorderLayout borderlayout = new BorderLayout();
		this.setLayout(borderlayout);

		JPanel gridsPanel = new JPanel();
		GridLayout gridLayout = new GridLayout(length, width);
		gridsPanel.setLayout(gridLayout);

		skyscrapers = new Skyscraper[length][width];
		for (int i = 0; i < length; i++) {
			for (int j = 0; j < width; j++) {
				skyscrapers[i][j] = new Skyscraper(i, j);
				skyscrapers[i][j].setLevel(random.nextInt(4) + 1);
				setNeighbors(skyscrapers[i][j]);
				gridsPanel.add(skyscrapers[i][j]);
			}
		}

		this.add(gridsPanel, BorderLayout.CENTER);// 1

		JPanel showPanel = new JPanel();
		showPanel.setLayout(new BorderLayout());
		JButton optimizeJb = new JButton("Optimize");
		optimizeJb.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Skyscrapers.this.optimize3();
			}
		});
		showPanel.add(optimizeJb, BorderLayout.WEST);
		sumText = new JTextArea();
		sumText.setText(this.getSum() + "");
		sumText.setToolTipText("show summation");
		sumText.setEditable(false);
		showPanel.add(sumText, BorderLayout.CENTER);

		this.add(showPanel, BorderLayout.SOUTH);// 2
		// this.setVisible(true);
	}

	/**
	 * 给指定大楼设定邻居
	 * 
	 * @param skyscraper
	 */
	public void setNeighbors(Skyscraper skyscraper) {
		int i = skyscraper.i;
		int j = skyscraper.j;
		if (i - 1 >= 0 && i - 1 < length && skyscrapers[i - 1][j] != null) {
			skyscraper.setNeighbor(skyscrapers[i - 1][j]);
		}
		if (i + 1 >= 0 && i + 1 < length && skyscrapers[i + 1][j] != null) {
			skyscraper.setNeighbor(skyscrapers[i + 1][j]);
		}
		if (j - 1 >= 0 && j - 1 < length && skyscrapers[i][j - 1] != null) {
			skyscraper.setNeighbor(skyscrapers[i][j - 1]);
		}
		if (j + 1 >= 0 && j + 1 < length && skyscrapers[i][j + 1] != null) {
			skyscraper.setNeighbor(skyscrapers[i][j + 1]);
		}
	}

	/**
	 * 不影响规则的情况下尽量升级
	 * 
	 */
	protected void optimize() {
		printStr("----optimize()...");
		for (int i = 0; i < length; i++) {
			for (int j = 0; j < width; j++) {
				setMaxLevel(skyscrapers[i][j], 4);
				// printStr(skyscrapers[i][j] + ":" +
				// skyscrapers[i][j].getLevel());
			}
		}
		this.sumText.setText("" + this.getSum());
	}

	protected void optimize2() {
		printStr("----optimize2()...");
		int num = 0;
		while (num < 1000) {
			int i = random.nextInt(4);
			int j = random.nextInt(4);
			setMaxLevel(skyscrapers[i][j], 4);
			printStr(skyscrapers[i][j] + ":" + skyscrapers[i][j].getLevel());
			num++;
		}
		this.sumText.setText("" + this.getSum());
	}

	protected void optimize3() {
		printStr("----optimize3()...");
		for (int lev = 1; lev <= 4; lev++) {
			for (int i = 0; i < length; i++) {
				for (int j = 0; j < width; j++) {
					if (skyscrapers[i][j].getLevel() == lev) {
						setMaxLevel(skyscrapers[i][j], 4);
						printStr(skyscrapers[i][j] + ":" + skyscrapers[i][j].getLevel());
					}
				}
			}
		}
		this.sumText.setText("" + this.getSum());
	}

	/**
	 * 尽可能大的设置级别
	 * 
	 * @param skyscraper
	 * @param level
	 */
	private void setMaxLevel(Skyscraper skyscraper, int level) {
		skyscraper.setLevel(level);
		if (level == 1)
			return;
		if (!beUpToTheMustard(skyscraper)) {
			setMaxLevel(skyscraper, level - 1);
		}
	}

	private void printStr(String str) {
		if (bPrint)
			System.out.println(str);
	}

	/**
	 * 是否符合标准
	 * 
	 * @param skyscraper
	 * @return
	 */
	public boolean beUpToTheMustard(Skyscraper skyscraper) {
		int level = skyscraper.getLevel();
		List neighbors = skyscraper.neighborList;
		if (neighbors == null || neighbors.isEmpty())
			return false;
		if (!hasLowLevel(skyscraper, level - 1)) {
			return false;
		}
		Skyscraper aneighbor;
		for (int n = 0; n < neighbors.size(); n++) {
			aneighbor = (Skyscraper) neighbors.get(n);
			if (!hasLowLevel(aneighbor, aneighbor.getLevel() - 1))
				return false;
		}
		return true;
	}

	/**
	 * 是否含有此级别及以下的邻居
	 * 
	 * @param skyscraper
	 * @param level
	 * @return
	 */
	public boolean hasLowLevel(Skyscraper skyscraper, int level) {
		if (level == 0)
			return true;
		List neighbors = skyscraper.neighborList;
		if (neighbors == null || neighbors.isEmpty())
			return false;
		Iterator it = neighbors.iterator();
		while (it.hasNext()) {
			if (((Skyscraper) it.next()).getLevel() == level) {
				return hasLowLevel(skyscraper, level - 1);
			}
		}
		return false;
	}

	public int getSum() {
		int sum = 0;
		for (int i = 0; i < length; i++) {
			for (int j = 0; j < width; j++) {
				sum += skyscrapers[i][j].getLevel();
			}
		}
		return sum;
	}

	public static void main(String[] args) {
		for (int i = 0; i < 10000; i++) {
			Skyscrapers skyscrapers = new Skyscrapers(5, 5);
			skyscrapers.init();
			skyscrapers.optimize();
			skyscrapers.optimize();
			int sum = skyscrapers.getSum();
			skyscrapers.printStr("sum = " + sum);
			if (sum > 61)
				skyscrapers.setVisible(true);
			else
				skyscrapers.dispose();
		}
	}
}

/**
 * 一座摩天大楼
 * 
 * @author Administrator
 * 
 */
@SuppressWarnings("serial")
class Skyscraper extends JButton {
	int i, j;

	private int level = 4;// 分四级，2必须与1相邻，3必须与1、2相邻，4必须与1、2、3相邻

	List<Skyscraper> neighborList;

	Skyscraper(int i, int j) {
		this.i = i;
		this.j = j;
		neighborList = new ArrayList<Skyscraper>(4);
		this.setText("" + level);
		this.setToolTipText(this.toString());
	}

	public void setNeighbor(Skyscraper skyscraper) {
		if (!neighborList.contains(skyscraper)) {
			neighborList.add(skyscraper);
			skyscraper.neighborList.add(this);
			// System.out.println(this + " border upon " + skyscraper);
		}
	}

	public String toString() {
		return "Skyscraper[" + i + "][" + j + "]";
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
		this.setText("" + level);
	}

}
